﻿using System.Text;

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http.Metadata;
using Microsoft.OpenApi.Models;

using Swashbuckle.AspNetCore.SwaggerGen;

namespace JackProjectTemplate.Web.Filters
{
    public class SwaggerOperationFilter : IOperationFilter
    {
        private static readonly string[] _value = ["global"];

        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
            ArgumentNullException.ThrowIfNull(operation);
            ArgumentNullException.ThrowIfNull(context);

            if (string.IsNullOrEmpty(operation.Summary))
            {
                string? text = null;
                text = (from s in context.ApiDescription.ActionDescriptor?.EndpointMetadata?.OfType<IEndpointSummaryMetadata>()
                        select s.Summary).LastOrDefault();
                operation.Summary = text;
            }

            if (string.IsNullOrEmpty(operation.Description))
            {
                string? text2 = null;
                text2 = (from s in context.ApiDescription.ActionDescriptor?.EndpointMetadata?.OfType<IEndpointDescriptionMetadata>()
                         select s.Description).LastOrDefault();
                operation.Description = text2;
            }

            if (string.IsNullOrEmpty(operation.OperationId))
            {
                operation.OperationId = FriendlyId(context.ApiDescription.RelativePath, context.ApiDescription.HttpMethod);
            }

            // 身份校验判断
            if (context.MethodInfo.IsDefined(typeof(AuthorizeAttribute), true) != true && context.MethodInfo.DeclaringType?.IsDefined(typeof(AuthorizeAttribute), true) != true && context.MethodInfo.DeclaringType?.BaseType?.IsDefined(typeof(AuthorizeAttribute), true) != true) return;
            // 匿名判断
            if (context.MethodInfo.IsDefined(typeof(AllowAnonymousAttribute), true) == true || context.MethodInfo.DeclaringType?.IsDefined(typeof(AllowAnonymousAttribute), true) == true) return;

            operation.Security = new List<OpenApiSecurityRequirement>
            {
                new() {
                    {
                        new OpenApiSecurityScheme
                        {
                            Name = "Authorization",
                            Type = SecuritySchemeType.ApiKey,
                            In = ParameterLocation.Header,
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Authorization"
                            },
                            BearerFormat = "JWT",
                            Scheme = "Bearer"
                        },
                        _value
                    }
                }
            };
        }

        private static string FriendlyId(string? relativePath, string? httpMethod)
        {
            string[] array = (relativePath?.Split('?').First() + "/" + httpMethod?.ToLower()).Split('/');
            StringBuilder stringBuilder = new();
            string[] array2 = array;
            foreach (string text in array2)
            {
                string value = text.Trim('{', '}');
                stringBuilder.AppendFormat("{0}{1}", text.StartsWith('{') ? "By" : string.Empty, ToTitleCase(value));
            }

            return stringBuilder.ToString();
        }

        private static string ToTitleCase(string value)
        {
            string result;
            if (!string.IsNullOrEmpty(value))
            {
                result = char.ToUpperInvariant(value[0]) + value[1..];
            }
            else
            {
                result = value;
            }

            return result;
        }
    }
}
